using System;
using System.IO;
using System.Globalization;

namespace mfXmlSerializer
{
    /// <summary>
    /// static container class 4 all string (& Co...) extension methods
    /// </summary>
    public static class mfStringExtensions
    {
        #region Fields

        private const string C_STR_BOOL_TRUE = "True";
        private const string C_STR_BOOL_FALSE = "False";

        #endregion

        #region Extensions

        public static String SerializeAsString(this bool value)
        {

            if (value)
            {
                return C_STR_BOOL_TRUE;
            }
            else
            {
                return C_STR_BOOL_FALSE;
            }
        }

        public static bool DeserializeBool(this String value)
        {
            if (value == C_STR_BOOL_TRUE)
            {
                return true;
            }
            else if (value == C_STR_BOOL_FALSE)
            {
                return false;
            }

            throw new mfXmlException(value + " is an invalid bool value");
        }

        public static MemoryStream ConvertToMemoryStream(this String s)
        {
            return new MemoryStream(System.Text.UTF8Encoding.UTF8.GetBytes(s));
        }

        static char[] C_STR_DATETIME_SPACESPLITTER = { 'T' };
        static char[] C_STR_DATETIME_DATESPLITTER = { '-' };
        static char[] C_STR_DATETIME_TIMESPLITTER = { ':' };
        static char[] C_STR_DATETIME_SUBTIMESPLITTER = { '+', '-' };
        public static DateTime ConvertToDateTime(this String dateTimeString)
        {
            try
            {
                //"YYYY-MM-ddTHH:mm:ss+HH:mm";
                var spaceSplit = dateTimeString.Split(C_STR_DATETIME_SPACESPLITTER, 2);

                var dateSplit = spaceSplit[0].Split(C_STR_DATETIME_DATESPLITTER, 3);
                var timeSplit = spaceSplit[1].Split(C_STR_DATETIME_TIMESPLITTER, 3);


                var year = Convert.ToInt32(dateSplit[0]);
                var month = Convert.ToInt32(dateSplit[1]);
                var day = Convert.ToInt32(dateSplit[2]);

                var hour = Convert.ToInt32(timeSplit[0]);
                var minute = Convert.ToInt32(timeSplit[1]);

                string second = timeSplit[2];
                if (second.IndexOfAny(C_STR_DATETIME_SUBTIMESPLITTER, 0) > 0)
                {
                    second = second.Split(C_STR_DATETIME_SUBTIMESPLITTER, 2)[0];
                }

                return new DateTime(year , month, day, hour, minute, Convert.ToInt32(second));
            }
            catch(Exception ex)
            {
                throw new mfXmlException("Error in 'ConvertToDateTime' 4 '" + dateTimeString + "'", ex);
            }
        }

        /// <summary>
        /// Indicates whether the specified string is null or an System.String.Empty string.
        /// </summary>
        /// <param name="value2Check">The string to test.</param>
        /// <returns>true if the value parameter is null or an empty string (""); otherwise, false.</returns>
        public static bool IsNullOrEmpty(this String value2Check)
        {
            if (value2Check == null)
            {
                return true;
            }

            if (value2Check == String.Empty)
            {
                return true;
            }
            return false;
        }

        public static Object ConvertToElementType(this String value, mfMapBaseElement mapElement)
        {
            if (mapElement.ElementType.Equals(typeof(String)))
            {
                return value;
            }
            else if (mapElement.ElementType.Equals(typeof(Int32)))
            {
                return Convert.ToInt32(value);
            }
            else if (mapElement.ElementType.Equals(typeof(UInt32)))
            {
                return Convert.ToUInt32(value);
            }
            else if (mapElement.ElementType.Equals(typeof(Double)))
            {
                return Convert.ToDouble(value);
            }
            else if (mapElement.ElementType.Equals(typeof(Boolean)))
            {
                return (value == C_STR_BOOL_TRUE) ? true : false;
            }
            else if (mapElement.ElementType.Equals(typeof(CultureInfo)))
            {
                return typeof(CultureInfo).CreateInstance(new Type[] { typeof(String) }, new object[] { value });
            }

            throw new mfXmlException(mapElement.ElementType + " is not support by deserialization");

        }

        public static bool IsNumber(this String value)
        {
            try
            {
                Convert.ToInt32(value);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public static int DeserializeEnumAsStringNumber(this String enumNumberValueAsString)
        {
            //maybe a bit lazy
            return Convert.ToInt32(enumNumberValueAsString);
        }
        #endregion

    }
}
